package com.ssyt.yt1.day31;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

class Person {

	private String name;

	public String getName() {
		return name;
	}
}

class Student {

	private String username;

	public String getName() {
		return username;
	}

	public Student(String username) {
		this.username = username;
	}
}

class Singleton {

	private static Singleton instance = new Singleton();

	private Singleton() {

	}

	public static Singleton getInstance() {
		return instance;
	}
}

public class HelloReflectDemo {

	/**
	 * 反射的认识
	 * 
	 * @throws ClassNotFoundException
	 * @throws NoSuchFieldException
	 * @throws SecurityException
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 */
	public static void test1() throws ClassNotFoundException,
			NoSuchFieldException, SecurityException, IllegalArgumentException,
			IllegalAccessException, InstantiationException {
		// 1、获取Class对象
		Class<?> clazz = Class.forName("com.ssyt.yt1.day31.Person");
		// 2、从Class获得要访问的对象信息（构造方法、方法、成员变量等）
		// Field[] fields = clazz.getDeclaredFields();
		// for (Field field : fields) {
		// System.out.println(field);
		// }
		Field field = clazz.getDeclaredField("name");
		field.setAccessible(true);
		// 3、对访问对象的具体操作（java.lang.reflect.*）
		Object obj = clazz.newInstance();
		field.set(obj, "张三");
		System.out.println(field.get(obj));
	}

	/**
	 * 判断某个对象是否有getName()方法，如果有，就调用它！
	 * 
	 * @throws ClassNotFoundException
	 * @throws InstantiationException
	 * @throws InvocationTargetException
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 */
	public static void test2(String fullName) throws ClassNotFoundException,
			IllegalAccessException, IllegalArgumentException,
			InvocationTargetException, InstantiationException {
		// 1、获取Class对象
		Class<?> clazz = Class.forName(fullName);
		// 2、从Class获得要访问的对象信息（构造方法、方法、成员变量等）
		Method[] methods = clazz.getDeclaredMethods();
		// 3、对访问对象的具体操作（java.lang.reflect.*）
		for (Method method : methods) {
			method.setAccessible(true);
			if ("getName".equals(method.getName())) {
				Object object = method.invoke(clazz.newInstance());
				if (!"void".equals(method.getReturnType().getName())) {
					System.out.println(object);
				}
			}
		}
	}

	/**
	 * Class对象是反射的源头，它的三种获取方式
	 * 
	 * @throws ClassNotFoundException
	 */
	public static void test3() throws ClassNotFoundException {
		// 1、通过Class.forName获取Class对象（框架里经常用到第一种方式！）
		Class<?> class1 = Class.forName("com.ssyt.yt1.day31.Person");
		// 2、类.class
		Class<?> class2 = Person.class;
		// 3、对象.getClass()
		Class<?> class3 = new Person().getClass();

		System.out.println(class1);
		System.out.println(class2);
		System.out.println(class3);
	}

	/**
	 * 通过反射去产生对象实例的两种方式（建议每个类都有一个空的构造方法）
	 * 
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 * @throws SecurityException
	 * @throws NoSuchMethodException
	 * @throws InvocationTargetException
	 * @throws IllegalArgumentException
	 */
	public static void test4() throws InstantiationException,
			IllegalAccessException, NoSuchMethodException, SecurityException,
			IllegalArgumentException, InvocationTargetException {
		Class<?> clazz = Student.class;
		// Class.newInstance()默认调用空的构造方法
		// System.out.println(clazz.newInstance());
		// 指定参数去构造对象
		Constructor<?> constructor = clazz.getConstructor(String.class);
		System.out.println(constructor.newInstance("张三"));
	}

	/**
	 * 有了反射，单例模式已不复存在！
	 * 
	 * @throws ClassNotFoundException
	 * @throws SecurityException
	 * @throws NoSuchMethodException
	 * @throws InvocationTargetException
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 */
	public static void test5() throws ClassNotFoundException,
			NoSuchMethodException, SecurityException, InstantiationException,
			IllegalAccessException, IllegalArgumentException,
			InvocationTargetException {
		Class<?> clazz = Class.forName("com.ssyt.yt1.day31.Singleton");
		Constructor<?> constructor = clazz.getDeclaredConstructor();
		constructor.setAccessible(true);
		for (int i = 0; i < 100; i++) {
			System.out.println(constructor.newInstance());
		}
	}

	public static void main(String[] args) throws ClassNotFoundException,
			NoSuchFieldException, SecurityException, IllegalArgumentException,
			IllegalAccessException, InvocationTargetException,
			InstantiationException, NoSuchMethodException {
		test1();
		// test2("com.ssyt.yt1.day31.Student");
		// test3();
		// test4();
		// test5();
	}
}
